package com.medical.literature.recognition.service.impl;

import com.medical.literature.common.exception.BusinessException;
import com.medical.literature.recognition.dto.RecognitionRequest;
import com.medical.literature.recognition.dto.RecognitionResult;
import com.medical.literature.recognition.entity.RecognitionTask;
import com.medical.literature.recognition.mapper.RecognitionTaskMapper;
import com.medical.literature.recognition.service.DocumentParseService;
import com.medical.literature.recognition.service.KeywordExtractionService;
import com.medical.literature.recognition.service.RecognitionService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 识别服务实现类
 */
@Service
@RequiredArgsConstructor
public class RecognitionServiceImpl implements RecognitionService {
    
    // 手动添加log变量
    private static final Logger log = LoggerFactory.getLogger(RecognitionServiceImpl.class);
    
    private final RecognitionTaskMapper recognitionTaskMapper;
    private final DocumentParseService documentParseService;
    private final KeywordExtractionService keywordExtractionService;

    @Override
    @Transactional
    public Long startRecognitionTask(RecognitionRequest request) {
        log.info("开始创建识别任务，请求参数: {}", request);
        // 创建识别任务
        RecognitionTask task = new RecognitionTask();
        task.setLiteratureId(request.getLiteratureId());
        task.setTaskType(request.getRecognitionType());
        task.setStatus(0); // 待处理
        task.setProgress(BigDecimal.ZERO);
        
        int result = recognitionTaskMapper.insert(task);
        if (result <= 0) {
            log.error("创建识别任务失败");
            throw new BusinessException("创建识别任务失败");
        }
        
        log.info("识别任务创建成功，任务ID: {}", task.getId());
        // 异步处理识别任务（这里简化为同步处理）
        try {
            processRecognitionAsync(task.getId(), request);
        } catch (Exception e) {
            log.error("启动识别任务失败: {}", e.getMessage(), e);
            // 更新任务状态为失败
            updateTaskStatus(task.getId(), 3, e.getMessage());
            // 重新抛出异常，确保调用方能够捕获到
            throw e;
        }
        
        log.info("识别任务处理完成，任务ID: {}", task.getId());
        return task.getId();
    }

    @Override
    public RecognitionResult getRecognitionStatus(Long taskId) {
        log.info("获取识别任务状态，任务ID: {}", taskId);
        RecognitionTask task = recognitionTaskMapper.selectById(taskId);
        if (task == null) {
            log.error("识别任务不存在，任务ID: {}", taskId);
            throw new BusinessException("识别任务不存在");
        }
        
        RecognitionResult result = new RecognitionResult();
        result.setLiteratureId(task.getLiteratureId());
        result.setStatus(task.getStatus());
        result.setErrorMessage(task.getErrorMessage());
        
        // 如果任务已完成，返回处理结果
        if (task.getStatus() == 2) {
            result.setConfidence(0.95); // 模拟置信度
        }
        
        log.info("识别任务状态获取完成，任务ID: {}, 状态: {}", taskId, task.getStatus());
        return result;
    }

    @Override
    @Transactional
    public RecognitionResult processRecognition(RecognitionRequest request) {
        log.info("开始处理识别任务: 文献ID={}, 类型={}", request.getLiteratureId(), request.getRecognitionType());
        
        RecognitionResult result = new RecognitionResult();
        result.setLiteratureId(request.getLiteratureId());
        
        try {
            switch (request.getRecognitionType()) {
                case 1: // 文本提取
                    log.info("处理文本提取任务");
                    result = processTextExtraction(request);
                    break;
                case 2: // OCR识别
                    log.info("处理OCR识别任务");
                    result = processOCRRecognition(request);
                    break;
                case 3: // 关键词提取
                    log.info("处理关键词提取任务");
                    result = processKeywordExtraction(request);
                    break;
                case 4: // 全部处理
                    log.info("处理完整识别任务");
                    result = processFullRecognition(request);
                    break;
                default:
                    log.error("不支持的识别类型: {}", request.getRecognitionType());
                    throw new BusinessException("不支持的识别类型: " + request.getRecognitionType());
            }
            
            result.setStatus(2); // 已完成
            log.info("识别任务处理完成: 文献ID={}", request.getLiteratureId());
            
        } catch (Exception e) {
            log.error("识别任务处理失败: {}", e.getMessage(), e);
            result.setStatus(3); // 失败
            result.setErrorMessage(e.getMessage());
            // 重新抛出异常，让调用方能够捕获到
            throw e;
        }
        
        return result;
    }
    
    /**
     * 异步处理识别任务
     */
    private void processRecognitionAsync(Long taskId, RecognitionRequest request) {
        log.info("开始异步处理识别任务，任务ID: {}, 请求参数: {}", taskId, request);
        // 更新任务状态为处理中
        updateTaskStatus(taskId, 1, null);
        
        try {
            // 处理识别
            RecognitionResult result = processRecognition(request);
            
            // 更新任务状态
            if (result.getStatus() == 2) {
                updateTaskStatus(taskId, 2, null);
            } else {
                updateTaskStatus(taskId, 3, result.getErrorMessage());
            }
            
        } catch (Exception e) {
            log.error("异步处理识别任务失败: {}", e.getMessage(), e);
            updateTaskStatus(taskId, 3, e.getMessage());
            // 重新抛出异常，确保上层能够捕获到
            throw e;
        }
    }
    
    /**
     * 更新任务状态
     */
    private void updateTaskStatus(Long taskId, Integer status, String errorMessage) {
        log.info("更新识别任务状态，任务ID: {}, 状态: {}, 错误信息: {}", taskId, status, errorMessage);
        RecognitionTask task = new RecognitionTask();
        task.setId(taskId);
        task.setStatus(status);
        task.setErrorMessage(errorMessage);
        
        if (status == 1) { // 处理中
            task.setStartTime(LocalDateTime.now());
            task.setProgress(BigDecimal.valueOf(0.5));
        } else if (status == 2 || status == 3) { // 已完成或失败
            task.setEndTime(LocalDateTime.now());
            task.setProgress(BigDecimal.valueOf(1.0));
        }
        
        recognitionTaskMapper.updateById(task);
        log.info("识别任务状态更新完成，任务ID: {}", taskId);
    }
    
    /**
     * 处理文本提取
     */
    private RecognitionResult processTextExtraction(RecognitionRequest request) {
        log.info("开始文本提取处理，请求参数: {}", request);
        String textContent = documentParseService.extractText(request.getFilePath(), request.getFileType());
        
        RecognitionResult result = new RecognitionResult();
        result.setLiteratureId(request.getLiteratureId());
        result.setTextContent(textContent);
        result.setConfidence(0.95);
        
        log.info("文本提取处理完成，文献ID: {}, 文本长度: {}", request.getLiteratureId(), textContent.length());
        return result;
    }
    
    /**
     * 处理OCR识别
     */
    private RecognitionResult processOCRRecognition(RecognitionRequest request) {
        log.info("开始OCR识别处理，请求参数: {}", request);
        String textContent = documentParseService.recognizeImageText(request.getFilePath());
        
        RecognitionResult result = new RecognitionResult();
        result.setLiteratureId(request.getLiteratureId());
        result.setTextContent(textContent);
        result.setConfidence(0.85); // OCR置信度通常较低
        
        log.info("OCR识别处理完成，文献ID: {}, 文本长度: {}", request.getLiteratureId(), textContent.length());
        return result;
    }
    
    /**
     * 处理关键词提取
     */
    private RecognitionResult processKeywordExtraction(RecognitionRequest request) {
        log.info("开始关键词提取处理，请求参数: {}", request);
        // 先提取文本
        String textContent = documentParseService.extractText(request.getFilePath(), request.getFileType());
        
        // 提取关键词
        List<String> keywords = keywordExtractionService.extractKeywords(textContent);
        
        RecognitionResult result = new RecognitionResult();
        result.setLiteratureId(request.getLiteratureId());
        result.setTextContent(textContent);
        result.setKeywords(keywords);
        result.setConfidence(0.90);
        
        log.info("关键词提取处理完成，文献ID: {}, 关键词数量: {}", request.getLiteratureId(), keywords.size());
        return result;
    }
    
    /**
     * 处理完整识别（文本提取 + 关键词提取）
     */
    private RecognitionResult processFullRecognition(RecognitionRequest request) {
        log.info("开始完整识别处理，请求参数: {}", request);
        try {
            // 文本提取
            String textContent = documentParseService.extractText(request.getFilePath(), request.getFileType());
            
            // 关键词提取
            List<String> keywords = keywordExtractionService.extractKeywords(textContent);
            
            // 医学术语提取
            List<String> medicalTerms = keywordExtractionService.extractMedicalTerms(textContent);
            if (medicalTerms != null) {
                keywords.addAll(medicalTerms);
            }
            
            // 去重
            keywords = keywords.stream().distinct().collect(java.util.stream.Collectors.toList());
            
            RecognitionResult result = new RecognitionResult();
            result.setLiteratureId(request.getLiteratureId());
            result.setTextContent(textContent);
            result.setKeywords(keywords);
            result.setConfidence(0.92);
            
            log.info("完整识别处理完成，文献ID: {}, 文本长度: {}, 关键词数量: {}", 
                     request.getLiteratureId(), textContent.length(), keywords.size());
            
            // 记录前几个关键词作为示例
            if (!keywords.isEmpty()) {
                int displayCount = Math.min(5, keywords.size());
                List<String> sampleKeywords = keywords.subList(0, displayCount);
                log.info("示例关键词: {}", sampleKeywords);
            }
            
            return result;
        } catch (Exception e) {
            log.error("完整识别处理失败: {}", e.getMessage(), e);
            throw e;
        }
    }
}